#include "multipipe.h"

int start(int argc, char** argv)
{
    printf("\n----------------------\nINITIALISATION started\n");
    int i;
    nbcmd = 0;
    cmd = (char**) malloc(sizeof (char*) *1);
    char *opt, *arg;
    for (i = 1; i < argc; i++)
    {
        opt = argv[i];
        if (opt[0] == '-' && strlen(opt) == 2)
        {
            switch (opt[1])
            {
                    /* mode debug */
                case 'd':
                    DEBUG = true;
                    printf("DEBUG activated\n");
                    break;
                    /* on enregistre la sortie de la première commande dans le fichier */
                case 'o':
                    if (i < argc - 1)
                    {
                        arg = argv[i + 1];
                        if (arg[0] != '-')
                        {
                            filename = (char*) malloc(sizeof (char) *strlen(arg));
                            printf("OUTPUT for first cmd activated in file: %s\n", arg);
                            filename = arg;
                            i++;
                            OUTPUT = true;
                        }
                        else
                        {
                            perror("error: missing filename after -o");
                            exit(0);
                        }
                    }
                    /* on affiche le fichier */
                    break;
                case 'f':
                    F = true;
                    printf("F activated: each command cmd0 | cmd M registerd in a file\n");
                    break;
            }
        }
        else if (opt[0] != '-')
        {
            cmd[nbcmd] = (char*) malloc(sizeof (char) *strlen(opt));
            cmd[nbcmd] = opt;
            if (DEBUG)
                printf("Command registered: %s\n", opt);
            nbcmd++;
        }
    }
    printf("INITIALISATION ended\n----------------------\n");
}

int routine()
{
    if (DEBUG)
        printf("Parse started\n");
    char **line, **ALL[nbcmd];
    int size, j, i, nb, prev, k;
    for (j = 0; j < nbcmd; j++)
    {
        size = strlen(cmd[j]);
        line = (char**) malloc(sizeof (char*) *1);
        i = 0;
        nb = 0;
        prev = 0;
        while (i < size)
        {
            if (cmd[j][i] == ' ')
            {
                line[nb] = (char*) malloc(sizeof (char) *i - prev);
                line[nb] = substr(cmd[j], prev, i - prev);
                prev = i + 1;
                nb++;
            }
            else if (i + 1 == size)
            {
                line[nb] = (char*) malloc(sizeof (char) *i + 1 - prev);
                line[nb] = substr(cmd[j], prev, i + 1 - prev);
                nb++;
            }
            i++;
        }
        line[nb] = NULL;
        nb++;
        ALL[j] = line;
        if (DEBUG)
        {
            printf("Command %i parsed: ", j);
            for (k = 0; k < nb; k++)
            {
                printf("%s ", ALL[j][k]);
            }
            printf("\n");
        }
    }
    if (DEBUG)
    {
        printf("Parse ended\n----------------------\n");
        printf("EXECUTION started\n");
    }
    //__EXECUTE____________________________________________________
    int new[2], f[2], res, n, pid, outfd;
    char* buffer = (char*) malloc(sizeof (char) *MAXLINE);
    char* name = (char*) malloc(sizeof (char));
    buffer = getFirstCMD(ALL[0]);
    for (j = 1; j < nbcmd; j++)
    {
        if (pipe(new) == -1)
        {
            perror("pipe failed\n");
            exit(-1);
        }
        switch ((pid = fork()))
        {
            case -1:
                perror("Erreur fork\n");
                exit(-1);
            case 0: //fils & petit fils
                if (F && pipe(f) == -1)
                {
                    perror("pipe failed\n");
                    exit(-1);
                }
                switch (fork())
                {
                    case -1:
                        perror("Erreur fork\n");
                        exit(-1);
                    case 0: //petit fils
                        close(new[READ]);
                        close(new[WRITE]);
                        if (F)
                        {
                            close(f[WRITE]);
                            sprintf(name, "cmd%i.txt", j);
                            printf("Command %i: %s | %s registered in %s\n",
                                    j, cmd[0], cmd[j], filename);
                            if ((outfd = creat(name, O_WRONLY | S_IRWXU)) < 0)
                            {
                                perror("creat file error\n");
                                exit(1);
                            }
                            if (DEBUG)
                                printf("Command %i: %s | %s\n*************\n", j, cmd[0], cmd[j]);
                            while ((n = read(f[READ], buffer, MAXLINE - 1)) > 0)
                            {
                                buffer[n] = 0;
                                if (DEBUG)
                                    printf("%s", buffer);
                                write(outfd, buffer, strlen(buffer));
                            }
                            if (n < 0)
                            {
                                perror("write error\n");
                                exit(1);
                            }
                            close(outfd);
                            close(f[READ]);
                        }
                        exit(0);
                        break;
                    default: //fils
                        close(new[WRITE]);
                        dup2(new[READ], IN);
                        close(new[READ]);
                        if (F)
                        {
                            close(f[READ]);
                            dup2(f[WRITE], OUT);
                            close(f[WRITE]);
                        }
                        else if (DEBUG)
                        {
                            printf("Command %i: %s | %s\n*************\n", j, cmd[0], cmd[j]);
                        }
                        res = execvp(ALL[j][0], ALL[j]);
                        if (res == -1)
                        {
                            printf("Error. Command not found: %s\n", ALL[j][0]);
                        }
                        perror("error exec\n");
                        exit(1);
                        break;
                }

                break;
            default: //parent
                close(new[READ]);
                if ((n = write(new[WRITE], buffer, strlen(buffer))) < 0)
                {
                    perror("error write\n");
                    exit(1);
                }
                break;
        }
    }
}

char *substr(char *src, int pos, int len)
{
    char *dest = NULL;
    if (len > 0)
    {
        /* allocation et mise à zéro */
        dest = calloc(len + 1, 1);
        /* vérification de la réussite de l'allocation*/
        if (NULL != dest)
        {
            strncat(dest, src + pos, len);
        }
    }
    return dest;
}

char* getFirstCMD(char** cmd)
{

    int new[2], res, pid, n, outfd;
    char* buffer = (char*) malloc(sizeof (char) *MAXLINE);
    char* result = (char*) malloc(sizeof (char));
    if (pipe(new) == -1)
    {
        perror("pipe failed\n");
        exit(-1);
    }
    switch ((pid = fork()))
    {
        case -1:
            perror("Erreur\n");
            exit(-1);
        case 0:
            close(new[READ]);
            dup2(new[WRITE], OUT);
            close(new[WRITE]);
            res = execvp(cmd[0], cmd);
            if (res == -1)
            {
                printf("Error. Command not found: %s\n", cmd[0]);
            }
            perror("error exec\n");
            exit(1);
            break;
        default:
            if (DEBUG)
                printf("Getting first command...\n");
            close(new[WRITE]);
            while ((n = read(new[READ], buffer, MAXLINE - 1)) > 0)
            {
                buffer[n] = 0;
                result = strcat(result, buffer);
                //printf("CHARS: %i\n%s", n, buffer);
            }
            if (n < 0)
            {
                perror("write error\n");
                exit(1);
            }
            close(new[READ]);
            if (OUTPUT)
            {
                if ((outfd = creat(filename, O_WRONLY | S_IRWXU)) < 0)
                {
                    perror("creat file error\n");
                    exit(1);
                }
                if (write(outfd, result, strlen(result)) < 0)
                {
                    perror("write error\n");
                    exit(1);
                }
                close(outfd);
                if (DEBUG)
                    printf("first command registered in %s:\n", filename);
            }
            if (DEBUG)
            {
                printf("\nCHARS: %i\n%s\n", (int) strlen(result), result);
                printf("...First command got\n");
            }
            return result;
            break;
    }
}


